﻿using SD.IOC.Core.Mediators;
using SD.Toolkits.Excel;
using SlamDunk.MES.DataDrive.Bussiness.Models.DefinitionContext;
using SlamDunk.MES.DataDrive.Common;
using SlamDunk.MES.DataDrive.Common.Attributes;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.DefinitionContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.DataDrive.Bussiness.Importers
{
    /// <summary>
    /// 导入产品定义
    /// </summary>
    [DataTag(13, "产品定义", "MES产品定义数据", DataDriveConfig.RealgoalName, DataDriveConfig.RealgoalConnectionStrings)]
    public class ImportDefinition
    {
        #region # 导入物料清单 —— void ImportFacilities()
        /// <summary>
        /// 导入物料清单
        /// </summary>
        [DataTag("导入物料清单")]
        public void ImportBoms()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            Bom[] boms = ExcelReader.ReadFile<Bom>(SystemConfig.InitalForDefinitionDataPath, "物料清单");
            BomItem[] bomItems = ExcelReader.ReadFile<BomItem>(SystemConfig.InitalForDefinitionDataPath, "物料清单项");

            IGrouping<string, BomItem>[] bomItemsGroups = bomItems.GroupBy(x => x.物料清单编号).ToArray();

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract
                    .GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            foreach (Bom bom in boms)
            {
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == bom.工厂模型编号)?.Id;
                Guid productId = ImportCacheData.MaterialInfos.Single(x => x.Number == bom.产品编号).Id;

                IGrouping<string, BomItem> specItems = bomItemsGroups.Single(x => x.Key == bom.物料清单编号);
                IList<BomItemParam> bomItemParams = new List<BomItemParam>();
                foreach (BomItem bomItem in specItems)
                {
                    bomItem.ConverterValue();

                    Guid materialId = ImportCacheData.MaterialInfos.Single(x => x.Number == bomItem.物料定义编号).Id;

                    BomItemParam bomItemParam = new BomItemParam
                    {
                        materialId = materialId,
                        directionType = bomItem.DirectionType,
                        quantity = bomItem.数量,
                        lossCoefficient = bomItem.耗损系数,
                        sort = bomItem.排序,
                        description = bomItem.描述
                    };
                    bomItemParams.Add(bomItemParam);
                }

                DateTime effectedDate = DateTime.Parse(bom.生效日期);
                DateTime expiredDate = DateTime.Parse(bom.失效日期);
                definitionContract.CreateBom(bom.物料清单编号, bom.物料清单名称, bom.版本号, productId, bom.运行规模, effectedDate, expiredDate, facilityId, bom.描述, bomItemParams);
            }
        }
        #endregion

        #region # 审核物料清单 —— void CheckProcesses()
        /// <summary>
        /// 审核物料清单
        /// </summary>
        [DataTag("审核物料清单")]
        public void CheckBoms()
        {
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();

            IEnumerable<BomInfo> bomInfos = definitionContract.GetBomsByPage(null, null, null, null, CheckStatus.Unchecked, 1, int.MaxValue).Datas;
            foreach (BomInfo bomInfo in bomInfos)
            {
                definitionContract.SubmitBom(bomInfo.Id);
                definitionContract.CheckBom(bomInfo.Id, true, "审核通过");
                definitionContract.EnableBom(bomInfo.Id);
            }
        }
        #endregion

        #region # 导入工艺类 —— void ImportProcessClasses()
        /// <summary>
        /// 导入工艺类
        /// </summary>
        [DataTag("导入工艺类")]
        public void ImportProcessClasses()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            ProcessClass[] processClasses = ExcelReader.ReadFile<ProcessClass>(SystemConfig.InitalForDefinitionDataPath, "工艺类");

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            foreach (ProcessClass processClass in processClasses)
            {
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == processClass.工厂模型编号)?.Id;

                definitionContract.CreateProcessClass(processClass.工艺类编号, processClass.工艺类名称, facilityId, processClass.描述);
            }
        }
        #endregion

        #region # 导入工艺 —— void ImportProcesses()
        /// <summary>
        /// 导入工艺
        /// </summary>
        [DataTag("导入工艺")]
        public void ImportProcesses()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            Process[] processes = ExcelReader.ReadFile<Process>(SystemConfig.InitalForDefinitionDataPath, "工艺");

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.ProcessClassInfos == null)
            {
                ImportCacheData.ProcessClassInfos = definitionContract.GetProcessClassesByPage(null, null, 1, int.MaxValue).Datas.ToList();
            }

            //创建工艺
            foreach (Process process in processes)
            {
                Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == process.工厂模型编号)?.Id;
                Guid processClassId = ImportCacheData.ProcessClassInfos.Single(x => x.Number == process.工艺类别编号).Id;
                Guid productId = ImportCacheData.MaterialInfos.Single(x => x.Number == process.产品编号).Id;

                DateTime effectedDate = DateTime.Parse(process.生效日期);
                DateTime expiredDate = DateTime.Parse(process.失效日期);
                definitionContract.CreateProcess(process.工艺编号, process.工艺名称, processClassId, process.版本号, productId, process.运行规模, facilityId, effectedDate, expiredDate, process.描述);
            }
        }
        #endregion

        #region # 导入工艺段 —— void ImportProcessSegments()
        /// <summary>
        /// 导入工艺段
        /// </summary>
        [DataTag("导入工艺段")]
        public void ImportProcessSegments()
        {
            IFoundationContract foundationContract = ResolveMediator.Resolve<IFoundationContract>();
            IResourceContract resourceContract = ResolveMediator.Resolve<IResourceContract>();
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();
            ProcessSegment[] processSegments = ExcelReader.ReadFile<ProcessSegment>(SystemConfig.InitalForDefinitionDataPath, "工艺段");
            SegmentPersonRule[] personRules = ExcelReader.ReadFile<SegmentPersonRule>(SystemConfig.InitalForDefinitionDataPath, "段人员规范");
            SegmentEquipmentRule[] equipmentRules = ExcelReader.ReadFile<SegmentEquipmentRule>(SystemConfig.InitalForDefinitionDataPath, "段设备规范");
            SegmentMaterialRule[] materialRules = ExcelReader.ReadFile<SegmentMaterialRule>(SystemConfig.InitalForDefinitionDataPath, "段物料规范");
            SegmentParameterRule[] parameterRules = ExcelReader.ReadFile<SegmentParameterRule>(SystemConfig.InitalForDefinitionDataPath, "段参数规范");

            #region # 缓存数据

            if (ImportCacheData.FacilityInfos == null)
            {
                ImportCacheData.FacilityInfos = foundationContract.GetFacilities(null, null, null, null).ToList();
            }
            if (ImportCacheData.PersonClassInfos == null)
            {
                ImportCacheData.PersonClassInfos = resourceContract.GetPersonClasses(null, null, null).ToList();
            }
            if (ImportCacheData.WorkStationInfos == null)
            {
                ImportCacheData.WorkStationInfos = foundationContract.GetWorkStationsByPage(null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.PersonInfos == null)
            {
                ImportCacheData.PersonInfos = resourceContract.GetPersonsByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.EquipmentClassInfos == null)
            {
                ImportCacheData.EquipmentClassInfos = resourceContract.GetEquipmentClasses(null, null, null).ToList();
            }
            if (ImportCacheData.EquipmentInfos == null)
            {
                ImportCacheData.EquipmentInfos = resourceContract.GetEquipmentsByPage(null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.MaterialInfos == null)
            {
                ImportCacheData.MaterialInfos = resourceContract.GetMaterialsByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.ProcessClassInfos == null)
            {
                ImportCacheData.ProcessClassInfos = definitionContract.GetProcessClassesByPage(null, null, 1, int.MaxValue).Datas.ToList();
            }
            if (ImportCacheData.ProcessInfos == null)
            {
                ImportCacheData.ProcessInfos = definitionContract.GetProcessesByPage(null, null, null, null, null, null, 1, int.MaxValue).Datas.ToList();
            }

            #endregion

            IGrouping<string, SegmentPersonRule>[] personRuleGroups = personRules.GroupBy(x => x.工艺段编号).ToArray();
            IGrouping<string, SegmentEquipmentRule>[] equipmentRuleGroups = equipmentRules.GroupBy(x => x.工艺段编号).ToArray();
            IGrouping<string, SegmentMaterialRule>[] materialRuleGroups = materialRules.GroupBy(x => x.工艺段编号).ToArray();
            IGrouping<string, SegmentParameterRule>[] parameterRuleGroups = parameterRules.GroupBy(x => x.工艺段编号).ToArray();

            //创建工艺段
            foreach (ProcessSegment segment in processSegments)
            {
                IGrouping<string, SegmentPersonRule> personRuleGroup = personRuleGroups.SingleOrDefault(x => x.Key == segment.工艺段编号);
                IGrouping<string, SegmentEquipmentRule> equipmentRuleGroup = equipmentRuleGroups.SingleOrDefault(x => x.Key == segment.工艺段编号);
                IGrouping<string, SegmentMaterialRule> materialRuleGroup = materialRuleGroups.SingleOrDefault(x => x.Key == segment.工艺段编号);
                IGrouping<string, SegmentParameterRule> parameterRuleGroup = parameterRuleGroups.SingleOrDefault(x => x.Key == segment.工艺段编号);

                //人员规范
                IList<SegmentPersonRuleParam> personRuleParams = new List<SegmentPersonRuleParam>();
                if (personRuleGroup != null)
                {
                    foreach (SegmentPersonRule personRule in personRuleGroup)
                    {
                        Guid? personClassId = ImportCacheData.PersonClassInfos.SingleOrDefault(x => x.Number == personRule.人员类编号)?.Id;
                        Guid? personId = ImportCacheData.PersonInfos.SingleOrDefault(x => x.Number == personRule.人员编号)?.Id;
                        Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == personRule.工厂模型编号)?.Id;
                        SegmentPersonRuleParam personRuleParam = new SegmentPersonRuleParam
                        {
                            personClassId = personClassId,
                            personId = personId,
                            personUse = personRule.人员用途,
                            quantity = string.IsNullOrWhiteSpace(personRule.数量) ? (decimal?)null : decimal.Parse(personRule.数量),
                            facilityId = facilityId,
                            sort = personRule.排序,
                            description = personRule.描述
                        };
                        personRuleParams.Add(personRuleParam);
                    }
                }

                //设备规范
                IList<SegmentEquipmentRuleParam> equipmentRuleParams = new List<SegmentEquipmentRuleParam>();
                if (equipmentRuleGroup != null)
                {
                    foreach (SegmentEquipmentRule equipmentRule in equipmentRuleGroup)
                    {
                        Guid? equipmentClassId = ImportCacheData.EquipmentClassInfos.SingleOrDefault(x => x.Number == equipmentRule.设备类编号)?.Id;
                        Guid? equipmentId = ImportCacheData.EquipmentInfos.SingleOrDefault(x => x.Number == equipmentRule.设备编号)?.Id;
                        Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == equipmentRule.工厂模型编号)?.Id;
                        SegmentEquipmentRuleParam equipmentRuleParam = new SegmentEquipmentRuleParam
                        {
                            equipmentClassId = equipmentClassId,
                            equipmentId = equipmentId,
                            equipmentUse = equipmentRule.设备用途,
                            quantity = string.IsNullOrWhiteSpace(equipmentRule.数量) ? (decimal?)null : decimal.Parse(equipmentRule.数量),
                            facilityId = facilityId,
                            sort = equipmentRule.排序,
                            description = equipmentRule.描述
                        };
                        equipmentRuleParams.Add(equipmentRuleParam);
                    }
                }

                //物料规范
                IList<SegmentMaterialRuleParam> materialRuleParams = new List<SegmentMaterialRuleParam>();
                if (materialRuleGroup != null)
                {
                    foreach (SegmentMaterialRule materialRule in materialRuleGroup)
                    {
                        materialRule.ConverterValue();

                        Guid materialId = ImportCacheData.MaterialInfos.SingleOrDefault(x => x.Number == materialRule.物料定义编号).Id;
                        Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == materialRule.工厂模型编号)?.Id;
                        SegmentMaterialRuleParam materialRuleParam = new SegmentMaterialRuleParam
                        {
                            materialId = materialId,
                            directionType = materialRule.DirectionType,
                            quantity = string.IsNullOrWhiteSpace(materialRule.数量) ? (decimal?)null : decimal.Parse(materialRule.数量),
                            facilityId = facilityId,
                            sort = materialRule.排序,
                            description = materialRule.描述
                        };
                        materialRuleParams.Add(materialRuleParam);
                    }
                }

                //参数规范
                IList<SegmentParameterRuleParam> parameterRuleParams = new List<SegmentParameterRuleParam>();
                if (parameterRuleGroup != null)
                {
                    foreach (SegmentParameterRule parameterRule in parameterRuleGroup)
                    {
                        Guid? facilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == parameterRule.工厂模型编号)?.Id;
                        SegmentParameterRuleParam parameterRuleParam = new SegmentParameterRuleParam
                        {
                            parameterNo = parameterRule.参数编号,
                            parameterName = parameterRule.参数名称,
                            relatedVariableNo = parameterRule.对应变量编号,
                            standardValue = parameterRule.标准值,
                            maxValue = string.IsNullOrWhiteSpace(parameterRule.最大值) ? (decimal?)null : decimal.Parse(parameterRule.最大值),
                            minValue = string.IsNullOrWhiteSpace(parameterRule.最小值) ? (decimal?)null : decimal.Parse(parameterRule.最小值),
                            valueUnitNo = parameterRule.单位,
                            facilityId = facilityId,
                            sort = parameterRule.排序,
                            description = parameterRule.描述
                        };
                        parameterRuleParams.Add(parameterRuleParam);
                    }
                }

                Guid processId = ImportCacheData.ProcessInfos.Single(x => x.Number == segment.工艺编号).Id;
                Guid? segmentFacilityId = ImportCacheData.FacilityInfos.FirstOrDefault(x => x.Number == segment.工厂模型编号)?.Id;
                Guid? workStationId = ImportCacheData.WorkStationInfos.FirstOrDefault(x => x.Number == segment.工位编号)?.Id;
                DateTime dateTimeSpan = DateTime.Parse(segment.工时定额);
                TimeSpan durationQuota = dateTimeSpan.TimeOfDay;

                definitionContract.CreateProcessSegment(processId, segment.工艺段编号, segment.工艺段名称, durationQuota, null, segmentFacilityId, workStationId, FormMode.Complex, null, segment.是否需质检, segment.排序, segment.描述, personRuleParams, equipmentRuleParams, materialRuleParams, parameterRuleParams);
            }
        }
        #endregion

        #region # 审核工艺 —— void CheckProcesses()
        /// <summary>
        /// 审核工艺
        /// </summary>
        [DataTag("审核工艺")]
        public void CheckProcesses()
        {
            IDefinitionContract definitionContract = ResolveMediator.Resolve<IDefinitionContract>();

            IEnumerable<ProcessInfo> processInfos = definitionContract.GetProcessesByPage(null, null, null, null, null, CheckStatus.Unchecked, 1, int.MaxValue).Datas;
            foreach (ProcessInfo processInfo in processInfos)
            {
                IEnumerable<ProcessSegmentInfo> processSegmentInfos = definitionContract.GetProcessSegments(processInfo.Id);
                if (processSegmentInfos.Any())
                {
                    definitionContract.SubmitProcess(processInfo.Id);
                    definitionContract.CheckProcess(processInfo.Id, true, "审核通过");
                    definitionContract.EnableProcess(processInfo.Id);
                }
            }
        }
        #endregion
    }
}
